import type TiledMap from "tiled-types";
import type { TiledLayerObjectgroup } from "tiled-types";
import { globalScale } from "@/config/static";
import { SceneType, useSceneStore } from "@/store/sceneStore";

// 碰撞区域类型
export interface CollisionArea {
  type: "polygon" | "rectangle"; // 碰撞区域类型
  points?: { x: number; y: number }[]; // 多边形点坐标
  x?: number; // 矩形左上角x坐标
  y?: number; // 矩形左上角y坐标
  width?: number; // 矩形宽度
  height?: number; // 矩形高度
  disabled?: boolean; // 碰撞区域是否禁用
  isTree?: boolean; // 是否为树木的碰撞区域
}

/**
 * 存储所有的碰撞区域对象
 */
export const collisionAreas: CollisionArea[] = [];

/**
 * 提取地图中的碰撞区域
 * @param map 地图数据
 */
export const extractCollisionAreas = (map: TiledMap): void => {
  // 保存树木的碰撞区域
  const treeCollisions = collisionAreas.filter((area) => area.isTree === true);

  // 清空现有的碰撞区域
  collisionAreas.length = 0;

  // 重新添加树木的碰撞区域
  treeCollisions.forEach((area) => collisionAreas.push(area));

  map.layers.forEach((layer) => {
    if (layer.type === "objectgroup" && layer.name === "collision") {
      const objectLayer = layer as TiledLayerObjectgroup;
      objectLayer.objects.forEach((obj) => {
        if (obj.polygon) {
          // 处理多边形碰撞区域
          const points = obj.polygon.map((point) => ({
            x: point.x + obj.x,
            y: point.y + obj.y,
          }));
          collisionAreas.push({
            type: "polygon",
            points,
          });
        } else if (obj.width && obj.height) {
          // 处理矩形碰撞区域
          collisionAreas.push({
            type: "rectangle",
            x: obj.x,
            y: obj.y,
            width: obj.width,
            height: obj.height,
          });
        }
      });
    }
  });
  // console.log(`已加载 ${collisionAreas.length} 个碰撞区域`);
};

/**
 * 渲染碰撞区域
 * @param ctx 画布上下文
 * @param scale 缩放比例
 */
export const renderCollisionAreas = (
  ctx: CanvasRenderingContext2D,
  scale: number = 2
) => {
  ctx.save();

  // 设置碰撞区域的绘制样式
  ctx.strokeStyle = "rgba(255,0,0,0.8)";
  ctx.fillStyle = "rgba(255, 0, 0, 0.2)";
  ctx.lineWidth = 1;

  for (const area of collisionAreas) {
    // 跳过被禁用的碰撞区域
    if (area.disabled) continue;
    const currentScene = useSceneStore().currentScene;
    // 获取当前场景，跳过在房屋内的树木碰撞区域
    if (area.isTree && currentScene === SceneType.HOUSE) continue;

    if (area.type === "polygon" && area.points) {
      // 绘制多边形
      ctx.beginPath(); // 开始新的路径
      ctx.moveTo(area.points[0].x * scale, area.points[0].y * scale); // 移动到起点
      for (let i = 1; i < area.points.length; i++) {
        ctx.lineTo(area.points[i].x * scale, area.points[i].y * scale); // 绘制线段
      }

      ctx.closePath(); // 闭合路径
      ctx.fill(); // 填充路径
      ctx.stroke(); // 绘制路径的边框
    } else if (
      area.type === "rectangle" &&
      area.x !== undefined &&
      area.y !== undefined &&
      area.width !== undefined &&
      area.height !== undefined
    ) {
      // 绘制矩形
      ctx.fillRect(
        area.x * scale,
        area.y * scale,
        area.width * scale,
        area.height * scale
      );
      ctx.strokeRect(
        area.x * scale,
        area.y * scale,
        area.width * scale,
        area.height * scale
      ); // 绘制矩形边框
    } else {
      return console.error("未知的碰撞区域类型");
    }
  }
  ctx.restore();
};

/**
 * 检查点是否在多边形内
 * 使用射线法判断点是否在多边形内
 * @param point 玩家边界顶点的坐标
 * @param polygon 多边形的点坐标数组
 */
const isPointInPolygon = (
  point: { x: number; y: number },
  polygon: { x: number; y: number }[]
): boolean => {
  let inside = false; // 初始认为点在多边形外
  // 遍历多边形的每一条边
  // i是当前点，j是从最后一个点开始的，形成一条边
  for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
    // 获取当前处理边的两个端点坐标
    const xi = polygon[i].x,
      yi = polygon[i].y;
    const xj = polygon[j].x,
      yj = polygon[j].y;

    const intersect =
      yi > point.y !== yj > point.y &&
      point.x < ((xj - xi) * (point.y - yi)) / (yj - yi) + xi;
    // 每次发现一个交点，就切换内部/外部状态。如果交点总数为奇数，最终 inside 为 true ；如果为偶数，则为 false
    if (intersect) inside = !inside;
  }
  return inside;
};

/**
 * 检查点是否在矩形内
 * @param point 玩家边界顶点的坐标
 * @param rect 矩形的坐标和尺寸
 */
const isPointInRectangle = (
  point: { x: number; y: number },
  rect: { x: number; y: number; width: number; height: number }
): boolean => {
  return (
    point.x >= rect.x &&
    point.x <= rect.x + rect.width &&
    point.y >= rect.y &&
    point.y <= rect.y + rect.height
  );
};

/**
 * 检查玩家是否与任何碰撞区域相交
 * @param x 玩家X坐标
 * @param y 玩家Y坐标
 * @param width 玩家宽度
 * @param height 玩家高度
 * @param isItem 是否为物品
 * @param footHeight 玩家脚底高度
 * @returns 是否发生碰撞
 */
export const checkCollision = (
  x: number,
  y: number,
  width: number,
  height: number,
  objectType: "player" | "item" = "player",
  footHeight: number = height / 5
): boolean => {
  // 创建玩家脚部的碰撞盒
  let objectTypeBox;

  if (objectType === "player") {
    objectTypeBox = {
      x: x,
      y: y + height - footHeight,
      width: width,
      height: footHeight,
    };
  } else {
    objectTypeBox = {
      x: x,
      y: y,
      width: width,
      height: height,
    };
  }
  // 检查脚部碰撞盒四个顶点
  const objectTypeCorners = [
    { x: objectTypeBox.x, y: objectTypeBox.y }, // 左上角
    { x: objectTypeBox.x + objectTypeBox.width, y: objectTypeBox.y }, // 右上角
    {
      x: objectTypeBox.x + objectTypeBox.width,
      y: objectTypeBox.y + objectTypeBox.height,
    }, // 右下角
    { x: objectTypeBox.x, y: objectTypeBox.y + objectTypeBox.height }, // 左下角
  ];

  const currentScene = useSceneStore().currentScene;

  for (const area of collisionAreas) {
    if (area.disabled) continue;

    if (area.isTree && currentScene === SceneType.HOUSE) continue;

    if (area.type === "polygon" && area.points) {
      for (const corner of objectTypeCorners) {
        if (isPointInPolygon(corner, area.points)) {
          return true;
        }
      }
    } else if (
      area.type === "rectangle" &&
      area.x !== undefined &&
      area.y !== undefined &&
      area.width !== undefined &&
      area.height !== undefined
    ) {
      for (const corner of objectTypeCorners) {
        if (
          isPointInRectangle(corner, {
            width: area.width,
            height: area.height,
            x: area.x,
            y: area.y,
          })
        ) {
          return true;
        }
      }
    }
  }

  return false;
};

/**
 * 添加新的碰撞区域
 * @param area 新的碰撞区域
 * @return 新的碰撞区域的索引
 *
 */
export const addCollisionArea = (area: CollisionArea) => {
  // 标记为树木碰撞区域
  if (!area.isTree) {
    area.isTree = true;
  }

  // 检查是否已经存在相同位置的碰撞区域
  const existingIndex = collisionAreas.findIndex(
    (existing) =>
      existing.type === area.type &&
      existing.x === area.x &&
      existing.y === area.y &&
      existing.width === area.width &&
      existing.height === area.height
  );

  if (existingIndex !== -1) {
    collisionAreas[existingIndex].disabled = false;
    return existingIndex;
  }

  // 添加新的碰撞区域
  collisionAreas.push(area);
  // console.log(`添加碰撞区域，当前总数: ${collisionAreas.length}`);
  return collisionAreas.length - 1;
};

/**
 * 禁用指定索引的碰撞区域
 * @param index 要禁用的碰撞区域的索引
 */
export const disableCollisionAreas = (index: number): void => {
  if (collisionAreas[index]) {
    collisionAreas[index].disabled = true;
  }
};

/**
 * 启用指定索引的碰撞区域
 * @param index 要启用的碰撞区域的索引
 */
export const enableCollisionAreas = (index: number): void => {
  if (collisionAreas[index]) {
    collisionAreas[index].disabled = false;
  }
};

// 矩形碰撞检测
interface Rectangle {
  x: number;
  y: number;
  width: number;
  height: number;
}

/**
 * 检测两个矩形是否重叠
 * @param rect1 第一个矩形
 * @param rect2 第二个矩形
 * @returns 是否重叠
 */
export const isRectanglesOverlap = (
  rect1: Rectangle,
  rect2: Rectangle
): boolean => {
  // 检查两个矩形是否重叠
  return (
    rect1.x < rect2.x + rect2.width &&
    rect1.x + rect1.width > rect2.x &&
    rect1.y < rect2.y + rect2.height &&
    rect1.y + rect1.height > rect2.y
  );
};
